#include "window.h"
#include "Lamp.h"

const int PERIOD = 1000 / 60;

Lamp * lamp;

Window::Window(int w, int h)
{
	x = 0;
	y = 0;
	width = w;
	height = h;

	wire_frame = false;
	debug = false;

	picture = new Picture();
	lamp = new Lamp();
	lamp->PostGLInitialize();
}

Window::~Window()
{
}

bool Window::Initialize()
{
	//return picture->Initialize();
	if (this->skybox_container.Initialize("modern.jpg") == false)
	{
		cerr << "Failed to load sky box texture." << endl;
		return false;
	}
	return true;
}

void Window::TakeDown()
{
	picture->TakeDown();
}

bool GLReturnedError(char * s)
{
	return false;


	bool return_error = false;
	GLenum glerror;


	while ((glerror = glGetError()) != GL_NO_ERROR)
	{
		return_error = true;
		cerr << s << ": " << gluErrorString(glerror) << endl;
	}


	return return_error;
}

void Window::DisplayFunc()
{
	GLReturnedError("Window::DisplayFunc() on entry");
	ClearWindow();

	this->DrawSkybox();

	// wire frame toggling will affect everything drawn, so it can be set here
	glPolygonMode(GL_FRONT_AND_BACK, wire_frame ? GL_LINE : GL_FILL);
	glEnable(GL_DEPTH_TEST);

	//picture->Display();
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//glOrtho(-1, 1, -1, 1, 1, 10);
	gluPerspective(60, width / height, 1, 10);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	//glPushMatrix();
	glUseProgram(0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glEnable(GL_LIGHTING); //Enable lighting
	glEnable(GL_LIGHT0); //Enable light #0
	glEnable(GL_NORMALIZE); //Automatically normalize normals
	glShadeModel(GL_SMOOTH); //Enable smooth shading
	//glDisable(GL_LIGHTING);
	//glDisable(GL_DEPTH_TEST);
	glTranslated(0,0, -5);
	
	glutSolidSphere(.5, 10, 10);
	
	glPushMatrix();
	//glRotated(30, 1, 0, 0);
	glTranslated(2, 0, -2);
	lamp->Display();
	glPopMatrix();

	glutSwapBuffers();
	GLReturnedError("Window::DisplayFunc() on exit");
}

void Window::KeyboardFunc(unsigned char c, int x, int y)
{
	switch (c) {
		case 'x':
		case 'X':

		// escape
		case 27:
			glutLeaveMainLoop();
			return;

		case 'w':
		case 'W':
			wire_frame = !wire_frame;
			break;

		case 'd':
		case 'D':
			debug = !debug;
			break;
	}
}

void Window::MouseFunc(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		// mouse coordinates are measured from the top of the screen, but GL measures
		// coordinates from the bottom of the screen. That's why the source's y coordinate
		// is height - y rather than just y.
		glm::ivec2 source = glm::ivec2(x, this->height - y);

		// after the mouse has been clicked, the picture warps from source to destination
		// every frame, always working from the "original" picture, here meaning the image
		// when the mouse was last released. When the mouse is released, the warped image
		// becomes the new original.
		picture->SetSource(source);
		picture->SetDestination(source);
	}
}

void Window::MotionFunc(int x, int y)
{
	picture->SetDestination(glm::ivec2(x, this->height - y));
}

void Window::ReshapeFunc(int w, int h)
{
	// this prevents divide-by-zero errors
	if (h == 0)
	{
		return;
	}

	width = w;
	height = h;
	aspect = GLfloat(w / h);

	glutPostRedisplay();
}

void Window::TimerFunc(int value)
{
	extern void TimerFunc(int value);

	glutTimerFunc(PERIOD, TimerFunc, value);
	glutPostRedisplay();
}

void Window::ClearWindow()
{
	glViewport(0, 0, width, height);
	glClearColor(1, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void Window::DrawSkybox()
{
	double one_third = 1.0 / 3.0;
	double one_quarter = 1.0 / 4.0;

	glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(20.0, double(this->width) / double(this->height), 1, 10);
	glViewport(0, 0, this->width, this->height);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -5.5f);
	this->skybox_container.Bind();
	glEnable(GL_TEXTURE_2D);
	glScalef(2.4f, 1.5f, 3.0f);
	glBegin(GL_QUADS);
	/*glTexCoord2d(1.0 * one_quarter, 1 * one_third);
	glVertex3d(1, 1, -1);
	glTexCoord2d(2.0 * one_quarter, 1 * one_third);
	glVertex3d(-1, 1, -1);
	glTexCoord2d(2.0 * one_quarter, 2 * one_third);
	glVertex3d(-1, -1, -1);
	glTexCoord2d(1.0 * one_quarter, 2 * one_third);
	glVertex3d(1, -1, -1);*/

	glTexCoord2d(0, 0);
	glVertex3d(1, 1, -1);
	glTexCoord2d(1,0);
	glVertex3d(-1, 1, -1);
	glTexCoord2d(1, 1);
	glVertex3d(-1, -1, -1);
	glTexCoord2d(0, 1);
	glVertex3d(1, -1, -1);
	glEnd();
}